package momo.multitree.simulation.result;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;

public class StabDegradationRawData {
	
	private Map<String, Double[]> map;
	
	public StabDegradationRawData(String input) {
		map = getData(input);
	}
	
	private Map<String, Double[]> getData(String filename) {
		Map<String, Double[]> val = new LinkedHashMap<String, Double[]>();
		try {
			BufferedReader in = new BufferedReader(new FileReader(new File(filename)));
			String line = "";
			while ( ( line=in.readLine() ) != null ) {
				String[] tokens = line.split(",");
				String key = tokens[0];
				
				double c3 = Double.valueOf(tokens[1]);
				double c2 = Double.valueOf(tokens[2]);
				
				line = in.readLine();
				tokens = line.split(",");
				double c3_1 = Double.valueOf(tokens[1]);
				double c2_1 = Double.valueOf(tokens[2]);
				
				line = in.readLine();
				tokens = line.split(",");
				double c3_2 = Double.valueOf(tokens[1]);
				double c2_2 = Double.valueOf(tokens[2]);
				
				line = in.readLine();
				tokens = line.split(",");
				double c3_3 = Double.valueOf(tokens[1]);
				double c2_3 = Double.valueOf(tokens[2]);
				
				line = in.readLine();
				tokens = line.split(",");
				double c3_4 = Double.valueOf(tokens[1]);
				double c2_4 = Double.valueOf(tokens[2]);
				
				line = in.readLine();
				tokens = line.split(",");
				double c3_5 = Double.valueOf(tokens[1]);
				double c2_5 = Double.valueOf(tokens[2]);
				
				double sc3_1 = (c3_1 - c3) / c3;
				double sc3_2 = (c3_2 - c3) / c3;
				double sc3_3 = (c3_3 - c3) / c3;
				double sc3_4 = (c3_4 - c3) / c3;
				double sc3_5 = (c3_5 - c3) / c3;
				
				double sc2_1 = (c2_1 - c2) / c2;
				double sc2_2 = (c2_2 - c2) / c2;
				double sc2_3 = (c2_3 - c2) / c2;
				double sc2_4 = (c2_4 - c2) / c2;
				double sc2_5 = (c2_5 - c2) / c2;
				
				Double[] values = { c3, 
									c2,
									c3_1,
									c2_1,
									c3_2,
									c2_2,
									c3_3,
									c2_3,
									c3_4,
									c2_4,
									c3_5,
									c2_5,
									sc3_1,
									sc2_1,
									sc3_2,
									sc2_2,
									sc3_3,
									sc2_3,
									sc3_4,
									sc2_4,
									sc3_5,
									sc2_5
									};
				val.put(key, values);
			}
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return val;
	}
	
	private String toRawDataCSVFormat() {
		StringBuffer buffer = new StringBuffer();
		for ( String key : map.keySet() ) {
			Double[] d = map.get(key);
			buffer.append(
					key + "," +
					d[0] + "," + d[1] + "," +
					d[2] + "," + d[3] + "," +
					d[4] + "," + d[5] + "," +
					d[6] + "," + d[7] + "," +
					d[8] + "," + d[9] + "," +
					d[10] + "," + d[11] + "\n"
					);
		}
		return buffer.toString();
	}
	
	public void writeRawDataCSV(String output) {
		String data = toRawDataCSVFormat();
		writeToFile(output, data);
	}
	
	private String toDegradationScaledPerformanceCSVFormat() {
		StringBuffer buffer = new StringBuffer();
		for ( String key : map.keySet() ) {
			Double[] d = map.get(key);
			buffer.append( 
					key + "," +
					d[12] + "," + d[13] + "," +
					d[14] + "," + d[15] + "," +
					d[16] + "," + d[17] + "," +
					d[18] + "," + d[19] + "," +
					d[20] + "," + d[21] + "\n"
					);
		}
		return buffer.toString();
	}
	
	public void writeDegradationScaledPerformanceCSV(String output) {
		String data = toDegradationScaledPerformanceCSVFormat();
		writeToFile(output, data);
	}
	
	private String toDegradationAvgStdCSVFormat() {
		Vector<Double> sc3_1 = new Vector<Double>();
		Vector<Double> sc3_2 = new Vector<Double>();
		Vector<Double> sc3_3 = new Vector<Double>();
		Vector<Double> sc3_4 = new Vector<Double>();
		Vector<Double> sc3_5 = new Vector<Double>();
		Vector<Double> sc2_1 = new Vector<Double>();
		Vector<Double> sc2_2 = new Vector<Double>();
		Vector<Double> sc2_3 = new Vector<Double>();
		Vector<Double> sc2_4 = new Vector<Double>();
		Vector<Double> sc2_5 = new Vector<Double>();
		
		StringBuffer buffer = new StringBuffer();
		for ( String key : map.keySet() ) {
			Double[] d = map.get(key);
			sc3_1.add(d[12]);
			sc2_1.add(d[13]);
			sc3_2.add(d[14]);
			sc2_2.add(d[15]);
			sc3_3.add(d[16]);
			sc2_3.add(d[17]);
			sc3_4.add(d[18]);
			sc2_4.add(d[19]);
			sc3_5.add(d[20]);
			sc2_5.add(d[21]);
		}
		
		Double[] d_sc3_1 = sc3_1.toArray(new Double[0]);
		Double[] d_sc3_2 = sc3_2.toArray(new Double[0]);
		Double[] d_sc3_3 = sc3_3.toArray(new Double[0]);
		Double[] d_sc3_4 = sc3_4.toArray(new Double[0]);
		Double[] d_sc3_5 = sc3_5.toArray(new Double[0]);
		
		Double[] d_sc2_1 = sc2_1.toArray(new Double[0]);
		Double[] d_sc2_2 = sc2_2.toArray(new Double[0]);
		Double[] d_sc2_3 = sc2_3.toArray(new Double[0]);
		Double[] d_sc2_4 = sc2_4.toArray(new Double[0]);
		Double[] d_sc2_5 = sc2_5.toArray(new Double[0]);
		
		buffer.append(
				mean(d_sc3_1) + "," + stdDev(d_sc3_1) + "," +
				mean(d_sc2_1) + "," + stdDev(d_sc2_1) + "," + 
				mean(d_sc3_2) + "," + stdDev(d_sc3_2) + "," +
				mean(d_sc2_2) + "," + stdDev(d_sc2_2) + "," +
				mean(d_sc3_3) + "," + stdDev(d_sc3_3) + "," +
				mean(d_sc2_3) + "," + stdDev(d_sc2_3) + "," +
				mean(d_sc3_4) + "," + stdDev(d_sc3_4) + "," +
				mean(d_sc2_4) + "," + stdDev(d_sc2_4) + "," +
				mean(d_sc3_5) + "," + stdDev(d_sc3_5) + "," +
				mean(d_sc2_5) + "," + stdDev(d_sc2_5) + "\n"
				);
		
		return buffer.toString();
	}
	
	public void writeDegradationAvgStdCSV(String output) {
		String data = toDegradationAvgStdCSVFormat();
		writeToFile(output, data);
	}
	
	private void writeToFile(String filename, String result) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename));
			out.write(result);
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private double mean(Double[] values) {
		double sum = 0d;
		for ( double v : values )
			sum += v;
		return sum / values.length;
	}
	
	private double stdDev(Double[] values) {
		double mean = mean(values);
		double sum = 0;
		for ( double v : values )
			sum += Math.pow((v-mean), 2);
		return Math.sqrt( sum / (values.length-1) );
	}
	
	public static void main(String args[]) {
		String filename = "degradation_on_leave.log";
		StabDegradationRawData app = new StabDegradationRawData(filename);
		app.writeRawDataCSV( "stab_degradation_raw_data.csv" );
		app.writeDegradationScaledPerformanceCSV( "stab_degradation_relative_perf.csv" );
		app.writeDegradationAvgStdCSV( "stab_degradation_avg_std.csv" );
	}
	
}// end of class StabDegradationRawData
